from numpy import *
import operator


def create_data_set():
    group = array([
        [1.0, 1.1],
        [1.0, 1.0],
        [0, 0],
        [0, 0.1]
    ])
    labels = ['A', 'A', 'B', 'B']
    return group, labels


def classify0(inX, dataSet, labels, k):  # k临近法
    dataSetSize = dataSet.shape[0]  # shape 各个维度的长度
    diffMat = tile(inX, (dataSetSize, 1)) - dataSet  # tile重复inX,(4,1)次，得到4行1列的矩阵和dataSet相减
    sqDiffMat = diffMat ** 2  # 进行2次方
    sqDistances = sqDiffMat.sum(axis=1)  # axis=1 是第二维相加
    distances = sqDistances ** 0.5  # 根号得到的是距离
    sortedDistIndicies = distances.argsort()  # 得出每一项从小到大的排名[0.1,0,1.4,1.3] 结果是[1,0,3,2]
    classCount = {}
    for i in range(k):
        voteIlabel = labels[where(sortedDistIndicies == i)[0][0]]  # 前k个集的labels标签是什么
        classCount[voteIlabel] = classCount.get(voteIlabel, 0) + 1  # 该labels没有默认为0，接着加1
    sortedClassCount = sorted(classCount.items(), key=lambda x: x[1], reverse=True)  # classCount的迭代倒叙排列
    return sortedClassCount[0][0]


def file2matrix(filename="datingTestSet2.txt"):  # 文件读取
    fr = open(filename)
    arrayOLines = fr.readlines()
    numberOLines = len(arrayOLines)  # 文件的行数
    returnMat = zeros((numberOLines, 3))  # 创建一个一维是文件行数，二维是3的矩阵
    classLabelVector = []
    index = 0
    for line in arrayOLines:
        line = line.strip()  # 首尾去空格
        listFromLine = line.split('\t')
        returnMat[index, :] = listFromLine[0:3]
        classLabelVector.append(int(listFromLine[-1]))
        index += 1
    return returnMat, classLabelVector


def autoNorm(dataSet):  # 归一公式：newValue = (oldValue - min) / (max - min)
    minVals = dataSet.min(0)
    maxVals = dataSet.max(0)
    ranges = maxVals - minVals
    # normDataSet = zeros(shape(dataSet))
    m = dataSet.shape[0]
    normDataSet = dataSet - tile(minVals, (m, 1))
    normDataSet = normDataSet / tile(ranges, (m, 1))
    return normDataSet,ranges,minVals


def datingClassTest():  # 分类器验证
    hoRatio = 0.10
    datingDataMat, datingLabels = file2matrix()  # 读取数据生成数据集
    nornMat, ranges, minVals = autoNorm(datingDataMat)  # 用归一法处理数据集
    m = nornMat.shape[0]  # 数据总数
    numTestVecs = int(m * hoRatio)  # 用于测试的数量
    errorCount = 0.0
    for i in range(numTestVecs):
        classifierResult = classify0(nornMat[i, :], nornMat[numTestVecs:m, :], \
                                     datingLabels[numTestVecs:m], 3)
        print("the classifier came back with:%d,the real answer is:%d" \
              % (classifierResult, datingLabels[i]))
        if (classifierResult != datingLabels[i]): errorCount += 1.0
    print("the total error rate is :%f" % (errorCount / float(numTestVecs)))
